﻿namespace PowerSong.Utilities.CreateBible
    {
    using System;
    using System.Collections.Generic;
    using System.IO;
    using PowerSong.BibleSupport;
    using PowerSong.BibleSupport.FileArchive;

    /// <summary>
    /// This is a tool for creating Bible files in PowerSong File Archive format.
    /// </summary>
    public class Program
        {

        public static void Main(string[] args)
            {

            // Show banner
            Console.WriteLine("PowerSong Bible Archive Creation Tool.");
            Console.WriteLine("Created by Nicholas Hill, Hill Research 2013.");
            Console.WriteLine();

            try
                {

                // Get source file name
                if (args.Length == 1)
                    {

                    // Create target files
                    var fileName = args[0];
                    var bibleFileName = Path.GetFileNameWithoutExtension(fileName) + ".Bible";
                    var indexFileName = Path.GetFileNameWithoutExtension(fileName) + ".Index";
                    CreateBibleArchive(fileName, bibleFileName, indexFileName);

                    }
                else
                    {
                    throw new Exception("Please specify the file name of an input file.");
                    }

                Console.WriteLine("All done.");
#if DEBUG
                Console.ReadLine();
#endif

                }
            catch (Exception ex)
                {
                Console.WriteLine("ERROR: " + ex.Message);
                }

            }

        private static void CreateBibleArchive(string sourceFileName, string targetBibleFileName, string targetIndexFileName)
            {

            // Sanity checks
            if (!File.Exists(sourceFileName)) throw new Exception("The source file '" + sourceFileName + "' does not exist.");
            if (File.Exists(targetBibleFileName)) throw new Exception("The target bible file '" + targetBibleFileName + "' already exists.");
            if (File.Exists(targetIndexFileName)) throw new Exception("The target index file '" + targetIndexFileName + "' already exists.");

            // Read in the source file
            Console.WriteLine("Adding chapters to file table...");
            var chapters = new Dictionary<string, List<string>>();
            using (var fileIn = new StreamReader(new FileStream(sourceFileName, FileMode.Open)))
                {
                while (!fileIn.EndOfStream)
                    {

                    // Get data from the next, trimmed line
                    var nextLine = fileIn.ReadLine().Trim().Replace('\t', ' ');
                    if (!string.IsNullOrEmpty(nextLine))
                        {

                        // Determine where the space lies
                        var spaceIndex = nextLine.IndexOf(" ");
                        if (spaceIndex == -1)
                            {
                            Console.WriteLine("WARNING: Cannot parse line [" + nextLine + "]");
                            }
                        else
                            {

                            // Try to determine the reference
                            var referenceText = nextLine.Substring(0, spaceIndex);
                            var verseText = nextLine.Substring(referenceText.Length + 1);
                            var reference = BibleSupport.DetermineSingleReference(referenceText);
                            if (reference == null)
                                {
                                Console.WriteLine("WARNING: Cannot parse reference [" + nextLine + "]");
                                }
                            else
                                {

                                // Determine if we need to add a chapter
                                string chapterKey = BibleSupport.GetBookName(reference.Book) + " " + reference.Chapter.ToString();
                                if (!chapters.ContainsKey(chapterKey))
                                    {
                                    chapters.Add(chapterKey, new List<string>());
                                    }
                                chapters[chapterKey].Add(verseText);

                                }

                            }

                        }
                    }
                }

            Console.WriteLine();

            // Create temporary chapter files
            var fileTable = new FileTable();
            foreach (var bookChapter in chapters)
                {

                // Write into a temporary memory stream
                using (var memory = new MemoryStream())
                    {
                    using (var writer = new StreamWriter(memory))
                        {
                        for (var lineIndex = 0; lineIndex <= bookChapter.Value.Count - 1; lineIndex++)
                            {
                            writer.Write(bookChapter.Value[lineIndex]);
                            if (lineIndex != bookChapter.Value.Count - 1) writer.WriteLine();
                            }
                        }

                    // Add the file to the file table
                    var chapterFilename = bookChapter.Key + ".txt";
                    fileTable.AddFile(chapterFilename, memory.ToArray());

                    }

                }


            // Create the archive file
            Console.WriteLine("Creating archive file '" + targetBibleFileName + "'...");
            BibleIndex.CreateBibleFile(targetBibleFileName, fileTable);

            // Create the index
            Console.WriteLine("Creating index file '" + targetIndexFileName + "'...");
            BibleIndex.CreateIndexFile(targetBibleFileName, targetIndexFileName);

            }

        }

    }
